// This MFC Samples source code demonstrates using MFC Microsoft Office Fluent User Interface 
// (the "Fluent UI") and is provided only as referential material to supplement the 
// Microsoft Foundation Classes Reference and related electronic documentation 
// included with the MFC C++ library software.  
// License terms to copy, use or distribute the Fluent UI are available separately.  
// To learn more about our Fluent UI licensing program, please visit 
// http://msdn.microsoft.com/officeui.
//
// Copyright (C) Microsoft Corporation
// All rights reserved.

// wfdeqDoc.cpp : implementation of the CwfdeqDoc class
//

#include "stdafx.h"
// SHARED_HANDLERS can be defined in an ATL project implementing preview, thumbnail
// and search filter handlers and allows sharing of document code with that project.
#ifndef SHARED_HANDLERS
#include "wfdeq.h"
#endif
#include "mgl\mgl_w.h"
#include "wfdeqDoc.h"
#include <propkey.h>
#include "IDD_New_Dialog.h"
#include "IDD_Info_Dialog.h"
#include "IDD_GRAPH.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// CwfdeqDoc

IMPLEMENT_DYNCREATE(CwfdeqDoc, CDocument)

BEGIN_MESSAGE_MAP(CwfdeqDoc, CDocument)
	ON_COMMAND(IDC_DOMAINX, &CwfdeqDoc::OnDomainx)
	ON_COMMAND(IDC_DOMAINY, &CwfdeqDoc::OnDomainy)
	ON_COMMAND(IDC_LEFT_BOUNDARY, &CwfdeqDoc::OnLeftBoundary)
	ON_COMMAND(IDC_RIGHT_BOUNDARY, &CwfdeqDoc::OnRightBoundary)
	ON_COMMAND(IDC_TOP_BOUNDARY, &CwfdeqDoc::OnTopBoundary)
	ON_COMMAND(IDC_BOTTOM_BOUNDARY, &CwfdeqDoc::OnBottomBoundary)
	ON_COMMAND(IDC_INITIAL, &CwfdeqDoc::OnInitial)
	ON_COMMAND(IDC_AUXILIARY, &CwfdeqDoc::OnAuxiliary)
	ON_COMMAND(IDC_DOMAINT, &CwfdeqDoc::OnDomaint)
	ON_COMMAND(ID_SET_PDE, &CwfdeqDoc::OnSetPde)
	ON_COMMAND(IDC_NX, &CwfdeqDoc::OnNx)
	ON_COMMAND(IDC_NY, &CwfdeqDoc::OnNy)
	ON_COMMAND(IDC_SELECT_SCHEME, &CwfdeqDoc::OnSelectScheme)
	ON_COMMAND(IDC_EXACT, &CwfdeqDoc::OnExact)
	ON_COMMAND(IDC_EDIT_NAME, &CwfdeqDoc::OnEditName)
	ON_UPDATE_COMMAND_UI(IDC_BUTTON_U, &CwfdeqDoc::OnUpdateButtonU)
	ON_COMMAND(IDC_BUTTON_U, &CwfdeqDoc::OnButtonU)
	ON_COMMAND(IDC_BUTTON_V, &CwfdeqDoc::OnButtonV)
	ON_UPDATE_COMMAND_UI(IDC_BUTTON_V, &CwfdeqDoc::OnUpdateButtonV)
	ON_UPDATE_COMMAND_UI(IDC_DOMAINT, &CwfdeqDoc::OnUpdateDomaint)
	ON_COMMAND(IDC_NT, &CwfdeqDoc::OnNt)
	ON_COMMAND(IDC_SOLUTION_LIST, &CwfdeqDoc::OnSolutionList)
	ON_COMMAND(IDC_INFO, &CwfdeqDoc::OnInfo)
	ON_COMMAND(IDC_DLL_NAME, &CwfdeqDoc::OnDllName)
	ON_COMMAND(IDC_LOAD_SCHEME, &CwfdeqDoc::OnLoadScheme)
	ON_COMMAND(IDC_GRAPH_IT, &CwfdeqDoc::OnGraphIt)
END_MESSAGE_MAP()


// CwfdeqDoc construction/destruction

CwfdeqDoc::CwfdeqDoc()
	: pRibbon(NULL)
	, pdeq(NULL)
	, m_sExactU(_T("sin(pi/2*x)*sin(pi/2*y)"))
	, eGrid(NULL)
	, m_sName(_T("fd-Solution"))
	, m_nPdeType(0)
	, isUxChkd(1)
	, m_sExactV(_T(""))
	, pApp(NULL)
	, m_sNt(_T("100"))
{
		// TODO: add one-time construction code here
		// boundary strings for v are not yet added
		m_sDomainX = _T("(0,1)");
		m_sDomainY = _T("(0,1)");
		m_sDomainT = _T("1");
		m_sInitialU = _T("sin(x)+cos(y)");
		m_sInitialV = _T("cos(x)");
		m_sAuxiliary = _T("-2*(pi*pi/2/2)*sin(pi/2*x)*sin(pi/2*y)");
		m_sLeftBU = _T("0");
		m_sTopBU = _T("sin(pi/2*x)*sin(pi/2)");
		m_sBottomBU = _T("0");
		m_sRightBU = _T("sin(pi/2)*sin(pi/2*x)");
		m_sLeftBV = _T("");
		m_sRightBV = _T("");
		m_sTopBV = _T("");
		m_sBottomBV = _T("");
		pRibbon = 
			((CMDIFrameWndEx*) AfxGetMainWnd())->GetRibbonBar();
		ASSERT_VALID(pRibbon);
		pApp=(CwfdeqApp*)::AfxGetApp();
		//ribbon UI to initial values
		IDD_New_Dialog nudlg;
		nudlg.DoModal();
		m_nPdeType=nudlg.pdeType;
		m_sNx = _T("5");
		m_sNy = _T("5");
		m_nSelectScheme = 0;
		m_nLcmX = 0;
		m_nLcmY = 0;
		UpdateUI();
		// TODO: You may populate your ListView with items by directly accessing
		//  its list control through a call to GetListCtrl().
}

CwfdeqDoc::~CwfdeqDoc()
{
	if(pdeq)
		delete pdeq;
}

BOOL CwfdeqDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	// TODO: add reinitialization code here
	// (SDI documents will reuse this document)

	return TRUE;
}




// CwfdeqDoc serialization

void CwfdeqDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		// TODO: add loading code here
	}
}

#ifdef SHARED_HANDLERS

// Support for thumbnails
void CwfdeqDoc::OnDrawThumbnail(CDC& dc, LPRECT lprcBounds)
{
	// Modify this code to draw the document's data
	dc.FillSolidRect(lprcBounds, RGB(255, 255, 255));

	CString strText = _T("TODO: implement thumbnail drawing here");
	LOGFONT lf;

	CFont* pDefaultGUIFont = CFont::FromHandle((HFONT) GetStockObject(DEFAULT_GUI_FONT));
	pDefaultGUIFont->GetLogFont(&lf);
	lf.lfHeight = 36;

	CFont fontDraw;
	fontDraw.CreateFontIndirect(&lf);

	CFont* pOldFont = dc.SelectObject(&fontDraw);
	dc.DrawText(strText, lprcBounds, DT_CENTER | DT_WORDBREAK);
	dc.SelectObject(pOldFont);
}

// Support for Search Handlers
void CwfdeqDoc::InitializeSearchContent()
{
	CString strSearchContent;
	// Set search contents from document's data. 
	// The content parts should be separated by ";"

	// For example:  strSearchContent = _T("point;rectangle;circle;ole object;");
	SetSearchContent(strSearchContent);
}

void CwfdeqDoc::SetSearchContent(const CString& value)
{
	if (value.IsEmpty())
	{
		RemoveChunk(PKEY_Search_Contents.fmtid, PKEY_Search_Contents.pid);
	}
	else
	{
		CMFCFilterChunkValueImpl *pChunk = NULL;
		ATLTRY(pChunk = new CMFCFilterChunkValueImpl);
		if (pChunk != NULL)
		{
			pChunk->SetTextValue(PKEY_Search_Contents, value, CHUNK_TEXT);
			SetChunkValue(pChunk);
		}
	}
}

#endif // SHARED_HANDLERS

// CwfdeqDoc diagnostics

#ifdef _DEBUG
void CwfdeqDoc::AssertValid() const
{
	CDocument::AssertValid();
}

void CwfdeqDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG


// //updates edit boxes to match variables


void CwfdeqDoc::UpdateUI(void)
{

	//============DOMAINS==============
	CMFCRibbonEdit* pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_DOMAINX));
	pEdit->SetEditText(m_sDomainX);

	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_DOMAINY));
	pEdit->SetEditText(m_sDomainY);

	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_DOMAINT));
	pEdit->SetEditText(m_sDomainT);
	
	UpdateEqUI();

	//==========AUXILIARY============
	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_AUXILIARY));
	pEdit->SetEditText(m_sAuxiliary);

	if(pdeq){
		pRibbon->ShowContextCategories(ID_SOLVE,1);
		pRibbon->RecalcLayout();
		pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_NX));
		pEdit->SetEditText(m_sNx);
		pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_NY));
		pEdit->SetEditText(m_sNy);
		pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_NT));
		pEdit->SetEditText(m_sNt);
		CMFCRibbonComboBox* pCombo = DYNAMIC_DOWNCAST(CMFCRibbonComboBox,pRibbon->FindByID(IDC_SELECT_SCHEME));
		pCombo->RemoveAllItems();
		int count=pApp->schms[m_nPdeType].GetSize();
		while(count--)
			pCombo->AddItem(pApp->schms[m_nPdeType].GetAt(count));
	}
	else{
		pRibbon->ShowContextCategories(ID_SOLVE,0);
		pRibbon->RecalcLayout();
	}
}

//===Control Handles for variables update
void CwfdeqDoc::OnDomainx()
{
	CMFCRibbonEdit* pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_DOMAINX));
	m_sDomainX=pEdit->GetEditText();
}


void CwfdeqDoc::OnDomainy()
{
	CMFCRibbonEdit*  pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_DOMAINY));
	m_sDomainY=pEdit->GetEditText();
}

void CwfdeqDoc::OnDomaint()
{
	CMFCRibbonEdit*  pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_DOMAINT));
	m_sDomainT=pEdit->GetEditText();// TODO: Add your command handler code here
}


void CwfdeqDoc::OnLeftBoundary()
{
	CMFCRibbonEdit* pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_LEFT_BOUNDARY));
	m_sLeftBU=pEdit->GetEditText();
}

void CwfdeqDoc::OnTopBoundary()
{
	CMFCRibbonEdit*	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_TOP_BOUNDARY));
	m_sTopBU=pEdit->GetEditText();// TODO: Add your command handler code here
}

void CwfdeqDoc::OnRightBoundary()
{
	CMFCRibbonEdit*	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_RIGHT_BOUNDARY));
	m_sRightBU=pEdit->GetEditText();// TODO: Add your command handler code here
}

void CwfdeqDoc::OnBottomBoundary()
{
	CMFCRibbonEdit*	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_BOTTOM_BOUNDARY));
	m_sBottomBU=pEdit->GetEditText();// TODO: Add your command handler code here
}


void CwfdeqDoc::OnInitial()
{
	CMFCRibbonEdit*	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_INITIAL));
	m_sInitialU=pEdit->GetEditText();// TODO: Add your command handler code here
}


void CwfdeqDoc::OnAuxiliary()
{
	CMFCRibbonEdit*	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_AUXILIARY));
	m_sAuxiliary=pEdit->GetEditText();// TODO: Add your command handler code here
}



void CwfdeqDoc::OnExact()
{
	CMFCRibbonEdit*	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_EXACT));
	m_sExactU=pEdit->GetEditText();// TODO: Add your command handler code here
}

void CwfdeqDoc::OnSetPde()
{
	//TODO: more exceptions and error
	soList.RemoveAll();
	//domain extraction
	m_sDomainT.Trim();
	m_sDomainX.Trim();
	m_sDomainY.Trim();
	float d[4];
	int T=100;
	T=_ttoi(m_sDomainT);
	//procedure to extract domain float values
	int curPos1=0,curPos2=0,i=0;
	CString resToken1,resToken2;
	resToken1= m_sDomainX.Tokenize(_T(",:"),curPos1);
	resToken2= m_sDomainY.Tokenize(_T(",:"),curPos2);
	for(i=0;i<2 && resToken1 != _T("") && resToken2!=_T("");i++)
	{
		d[i]=_ttof(resToken1);
		d[i+2]=_ttof(resToken2);
		resToken1 = m_sDomainX.Tokenize(_T(",:"), curPos1);
		resToken2= m_sDomainY.Tokenize(_T(",:"),curPos2);
	};
	//simple conditions check
	if(i!=2 || d[0]==d[1] || d[2]==d[3] || T<0){
		::AfxMessageBox(_T("Check the Domain Values"));
		return;
	}

	CT2CA b0 (m_sLeftBU);

	CT2CA b1 (m_sTopBU);

	CT2CA b2 (m_sRightBU);
	CT2CA b3 (m_sBottomBU);
	CT2CA exact (m_sExactU);
	CT2CA aux (m_sAuxiliary);
	CT2CA initial (m_sInitialU);
	if(pdeq)
		delete pdeq;
	if(m_nPdeType<2)
		pdeq=new PDE(d[0],d[1],d[2],d[3],T,b0,b1,b2,b3,aux,exact,initial);
	else
	{
		CT2CA b10 (m_sLeftBV);
		CT2CA b11 (m_sTopBV);
		CT2CA b12 (m_sRightBV);
		CT2CA b13 (m_sBottomBV);
		CT2CA ev (m_sExactV);
		CT2CA iv (m_sInitialV);
		pdeq=new PDE(d[0],d[1],d[2],d[3],T,b0,b1,b2,b3,aux,exact,initial,b10,b11,b12,b13,ev,iv);
	}
	if(pdeq){
		pRibbon->ShowContextCategories(ID_SOLVE,1);
		CMFCRibbonCategory* pCategory=pRibbon->GetActiveCategory();
		int idn=pCategory->GetContextID()+1;
		if(!pCategory->IsVisible()) idn++;
		pRibbon->SetActiveCategory(pRibbon->GetCategory(idn));
		
		CMFCRibbonEdit*	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_NX));
		if(pEdit)
		pEdit->SetEditText(m_sNx);
		pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_NY));
		if(pEdit)
		pEdit->SetEditText(m_sNy);
		CMFCRibbonComboBox* pCombo = DYNAMIC_DOWNCAST(CMFCRibbonComboBox,pRibbon->FindByID(IDC_SELECT_SCHEME));
		pCombo->RemoveAllItems();
		int count=pApp->schms[m_nPdeType].GetSize();
		while(count--)
			pCombo->AddItem(pApp->schms[m_nPdeType].GetAt(count));
		pCombo = DYNAMIC_DOWNCAST(CMFCRibbonComboBox,pRibbon->FindByID(IDC_SOLUTION_LIST));
		pCombo->RemoveAllItems();
		pRibbon->RecalcLayout();
	}
	return;
}

//handles for solve ribbon
void CwfdeqDoc::OnNx()
{
	CMFCRibbonEdit*	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_NX));
	m_sNx=pEdit->GetEditText();// TODO: Add your command handler code here
}


void CwfdeqDoc::OnNy()
{
	CMFCRibbonEdit*	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_NY));
	m_sNy=pEdit->GetEditText();// TODO: Add your command handler code here
}

void CwfdeqDoc::OnNt()
{
	CMFCRibbonEdit*	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_NT));
	m_sNt=pEdit->GetEditText();// TODO: Add your command handler code here
}

void CwfdeqDoc::OnSelectScheme()
{
	CMFCRibbonComboBox* pCombo = DYNAMIC_DOWNCAST(CMFCRibbonComboBox,pRibbon->FindByID(IDC_SELECT_SCHEME));
	m_nSelectScheme=pCombo->GetCurSel();
}

void CwfdeqDoc::OnEditName()
{
	CMFCRibbonEdit*	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_EDIT_NAME));
	m_sName=pEdit->GetEditText();// TODO: Add your command handler code here
}

// TODO: Add your command handler code here

int CwfdeqDoc::UpdateFD(void)
{
	//getting current nx,ny and nt values
	m_sNx.Trim();
	m_sNy.Trim();
	m_sNt.Trim();
	int x=21,y=21,t=50;
	x=_ttoi(m_sNx)+1;
	y=_ttoi(m_sNy)+1;
	t=_ttoi(m_sNt);
	if(x<2)	x=3;
	if(y<2)	y=3;
	//getting current scheme selection
	CMFCRibbonComboBox* pCombo=DYNAMIC_DOWNCAST(CMFCRibbonComboBox,pRibbon->FindByID(IDC_SELECT_SCHEME));
	int sel=pCombo->GetCurSel();
	CString scm=pCombo->GetItem(sel);
	if(sel<0){ ::AfxMessageBox(L"Please Select/Load a Scheme");	return 0;}
	//searching thru list for pre-existing solutions
	int i;
	for(i=0;i<soList.GetSize();i++){
		CString temp(soList[i].scheme);
		if(soList[i].uGrid.getX()==x && soList[i].uGrid.getY()==y && soList[i].nt == t && scm==temp)
			break;
	}
	if(i<soList.GetSize()){
		CString temp;
		int fold;
		fold=m_nPdeType<2?2:3;
		temp.Format(_T("Solution for this discretization already exists with the name %s.\n Solution-list is Shown at column no. %d")
			,CString(soList[i].name),pdeq->isExact?(i)*fold+fold+1:i+fold);
		::AfxMessageBox(temp);
		return 0;
	}
	//create object with the specified name
	CMFCRibbonEdit* pname=DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_EDIT_NAME));
	CString name=pname->GetEditText();
	if(name=="")	name.Append(_T("fdSol"));
	name.Trim();
	CT2CA nm (name);
	CT2CA sm (scm);
	//cook solution
	cfdGrid aux(x,y);
	aux.fillGrid(pdeq->aux,pdeq->getDx(x),pdeq->getDy(y));
	if(m_nPdeType<2){
		fdSolution tp(x,y,sm,nm,0);
		tp.uGrid.fillGrid(pdeq->initial[0],pdeq->getDx(x),pdeq->getDy(y));
		tp.uGrid.fillBoundary(pdeq->bound[0],pdeq->getDx(x),pdeq->getDy(y));
		if(m_nPdeType==0){
			//PoissonScm2 sol;//scheme1
			//sol.solve(tp.uGrid,aux,pdeq->getDx(x),pdeq->getDy(y));
			typedef void  (*solveT)(cfdGrid &nsol, cfdGrid &aux,double dx,double dy);    // pointer to: int  function(int) 
			solveT pt=NULL;
			HINSTANCE scmdll=NULL;
			scmdll=LoadLibrary(scm);
			if(scmdll==NULL){
				::AfxMessageBox(_T("Dll can not be loaded. It seems it has been moved from the folder"));
				return 0;
			}
			pt = (solveT) GetProcAddress(scmdll, "solve");
			if(!pt){ AfxMessageBox(_T("The dll is broken can not load the solve method"));	return 0;}
			(pt)(tp.uGrid,aux,pdeq->getDx(x),pdeq->getDy(y));
			//Free the library:
			FreeLibrary(scmdll); 
			soList.Add(tp);
		}
		else{
			typedef void  (*solveT)(cfdGrid &nsol, cfdGrid &aux,double dx,double dy,long nt,double T);    // pointer to: int  function(int) 
			solveT pt=NULL;
			HINSTANCE scmdll=NULL;
			scmdll=LoadLibrary(scm);
			if(scmdll==NULL){
				::AfxMessageBox(_T("Dll can not be loaded. It seems it has been moved from the folder"));
				return 0;
			}
			pt = (solveT) GetProcAddress(scmdll, "solve");
			if(!pt){ AfxMessageBox(_T("The dll is broken can not load the solve method"));	return 0;}
			(pt)(tp.uGrid,aux,pdeq->getDx(x),pdeq->getDy(y),t,pdeq->getT());
			//Free the library:
			FreeLibrary(scmdll); 	
			soList.Add(tp);
		}
	}
	else{
		fdSolution tp(x,y,t,sm,nm,true);
		tp.uGrid.fillGrid(pdeq->initial[0],pdeq->getDx(x),pdeq->getDy(y));
		tp.uGrid.fillBoundary(pdeq->bound[0],pdeq->getDx(x),pdeq->getDy(y));
		tp.vGrid.fillGrid(pdeq->initial[1],pdeq->getDx(x),pdeq->getDy(y));
		tp.vGrid.fillBoundary(pdeq->bound[1],pdeq->getDx(x),pdeq->getDy(y));
		}
		if(m_nPdeType==2){
		//	PoissonScm2 sol;//scheme1
		//	sol.solve(tp.nGrid,aux,pdeq->getDx(x),pdeq->getDy(y));
		//}
		//else{
		//	scmdll=LoadLibrary(_T("cpdll.dll"));
		//	if(scmdll==NULL) return 0;
		//	::AfxMessageBox(_T("loaded dll"));

		// pfun1 = (MYFUN1) GetProcAddress(scmdll, "Scheme");
		// pfun2 = (MYFUN2) GetProcAddress(scmdll, "DLLfun2");
		// parg = (int*)GetProcAddress(scmdll,"DLLArg");

		// if(pfun1) AfxMessageBox(_T("loaded function 1\n"));
		// if(pfun2) AfxMessageBox(_T("loaded function 2\n"));
		// if(parg) AfxMessageBox(_T("loaded argument\n"));
  //    //Free the library:
		//FreeLibrary(scmdll);   
		//PoissonScm2 sol;//scheme1
		//sol.solve(tp.nGrid,aux,pdeq->getDx(x),pdeq->getDy(y));
		}
	pCombo = DYNAMIC_DOWNCAST(CMFCRibbonComboBox,pRibbon->FindByID(IDC_SOLUTION_LIST));
	pCombo->AddItem(CString(soList[soList.GetUpperBound()].name));
	//update eGrid
	if(updateLcm(x,y)){
		if(eGrid)
			delete eGrid;
		eGrid=new cfdGrid(m_nLcmX+1,m_nLcmY+1);
		if(pdeq->isExact){
			eGrid->fillGrid(pdeq->exact[0],pdeq->getDx(x),pdeq->getDy(y));
			if(m_nPdeType>1)
				eGrid->fillGrid(pdeq->exact[1],pdeq->getDx(x),pdeq->getDy(y));
		}
		return 2;
	}
	return 1;
}


PDE* CwfdeqDoc::getPde(void)
{
	return pdeq;
}


bool CwfdeqDoc::updateLcm(int nx, int ny)
{
	nx--;ny--;
	if(!m_nLcmX){	//bole toh its first entry
		m_nLcmX=nx;
		m_nLcmY=ny;
		return true;
	}
	int tempx=m_nLcmX,tempy=m_nLcmY;
	int res,div,temp;
	res=nx<m_nLcmX?nx,div=m_nLcmX:m_nLcmX,div=nx;
	while(temp=div%res){
		div=res;
		res=temp;
	}
	m_nLcmX=res;//ritenow storing gcd, for lcm =(nx*m_nLcmX)/res;
	res=nx<m_nLcmY?nx,div=m_nLcmY:m_nLcmY,div=nx;
	while(temp=div%res){
		div=res;
		res=temp;
	}
	m_nLcmY=res;//ritenow storing gcd, for lcm = (ny*m_nLcmY)/res;
	if(m_nLcmX!=tempx || m_nLcmY!=tempy)
		return true;
	else return false;
}

void CwfdeqDoc::OnButtonU()
{
	isUxChkd=true;
	UpdateEqUI();
}

void CwfdeqDoc::OnUpdateButtonU(CCmdUI *pCmdUI)
{
	pCmdUI->SetCheck(isUxChkd);
}


void CwfdeqDoc::OnButtonV()
{
	isUxChkd=false;
	UpdateEqUI();
}


void CwfdeqDoc::OnUpdateButtonV(CCmdUI *pCmdUI)
{
	if(m_nPdeType<2)
		pCmdUI->Enable(0);
	else
		pCmdUI->Enable(1);
	pCmdUI->SetCheck(!isUxChkd);
}


void CwfdeqDoc::OnUpdateDomaint(CCmdUI *pCmdUI)
{
	if(m_nPdeType%2)
		pCmdUI->Enable(1);
	else
		pCmdUI->Enable(0);
}


// called by Updates first Category of RiboonBar
void CwfdeqDoc::UpdateEqUI(void)
{
	//===========BOUNDARIES==============
	CMFCRibbonEdit* pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_LEFT_BOUNDARY));
	if(isUxChkd)	pEdit->SetEditText(m_sLeftBU);	else	pEdit->SetEditText(m_sLeftBV);

	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_TOP_BOUNDARY));
	if(isUxChkd)	pEdit->SetEditText(m_sTopBU);	else	pEdit->SetEditText(m_sTopBV);

	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_RIGHT_BOUNDARY));
	if(isUxChkd)	pEdit->SetEditText(m_sRightBU);	else	pEdit->SetEditText(m_sRightBV);

	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_BOTTOM_BOUNDARY));
	if(isUxChkd)	pEdit->SetEditText(m_sBottomBU);else	pEdit->SetEditText(m_sBottomBV);
	
	//=========INITIAL==============
	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_INITIAL));
	if(isUxChkd)	pEdit->SetEditText(m_sInitialU);else	pEdit->SetEditText(m_sInitialV);

	//==========Exact============
	pEdit = DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_EXACT));
	if(isUxChkd)	pEdit->SetEditText(m_sExactU);	else	pEdit->SetEditText(m_sExactV);
}


void CwfdeqDoc::OnSolutionList()
{
	// TODO: Add your command handler code here
}


void CwfdeqDoc::OnInfo()
{
	CMFCRibbonComboBox* pCombo=DYNAMIC_DOWNCAST(CMFCRibbonComboBox,pRibbon->FindByID(IDC_SELECT_SCHEME));
	int sel=pCombo->GetCurSel();
	if(sel<0){ ::AfxMessageBox(L"Please Select/Load a Scheme");	return;}
	CString scm=pCombo->GetItem(sel);
	typedef void  (*infoT)(char*);  
	infoT pt=NULL;
	HINSTANCE scmdll=NULL;
	scmdll=LoadLibrary(scm);
	if(!scmdll){
		::AfxMessageBox(_T("Dll can not be loaded. It seems it has been moved from the folder"));
		return;
	}
	pt = (infoT) GetProcAddress(scmdll, "info");
	if(!pt){ AfxMessageBox(_T("The dll has no extra information"));	return;}
	char* ar=new char[128];
	(pt)(ar);
	FreeLibrary(scmdll); 
	IDD_Info_Dialog dlg;
	CString s(ar);
	int curPos=0;
	CString info= s.Tokenize(_T("|"),curPos);
	CString link= s.Tokenize(_T("|"),curPos);
	dlg.setInfo(info,link);
	dlg.DoModal();
	//Free the library:
}


void CwfdeqDoc::OnDllName()
{
	// TODO: Add your command handler code here
}


void CwfdeqDoc::OnLoadScheme()
{
	CMFCRibbonEdit* pEdit=DYNAMIC_DOWNCAST(CMFCRibbonEdit,pRibbon->FindByID(IDC_DLL_NAME));
	CString scm=pEdit->GetEditText();
	if(scm==""){ ::AfxMessageBox(L"Please Write a dll file name to be loaded");	return;}
	typedef void  (*infoT)(char*);  
	typedef void  (*solveT0)(cfdGrid &nsol, cfdGrid &aux,double dx,double dy);
	typedef void  (*solveT1)(cfdGrid &nsol, cfdGrid &aux,double dx,double dy,long nt,double T);
	typedef void  (*solveT2)(cfdGrid &usol,cfdGrid &nsol, cfdGrid &aux,double dx,double dy);
	typedef void  (*solveT3)(cfdGrid &usol,cfdGrid &nsol, cfdGrid &aux,double dx,double dy,long nt,double T);
	infoT infoptr=NULL;
	HINSTANCE scmdll=NULL;
	CString sh;
	scmdll=LoadLibrary(scm);
	if(!scmdll){
		::AfxMessageBox(_T("Dll can not be located. Check if you have copied the dll to app folder and the name you have entered is correct"));
		return;
	}
	solveT0 solveptr = (solveT0) GetProcAddress(scmdll, "solve");
	if(solveptr){
		pApp->schms[0].Add(scm);
		sh.Append(_T("The scheme has been added to solve one-variable unsteady PDE's\n"));
	}
	else{
		solveT1 solveptr=(solveT1)	GetProcAddress(scmdll, "solve");
		if(solveptr){
			pApp->schms[1].Add(scm);
			sh.Append(_T("The scheme has been added to solve one-variable steady PDE's\n"));
		}
		else{
			solveT2 solveptr=(solveT2)	GetProcAddress(scmdll, "solve");
			if(solveptr){
				pApp->schms[2].Add(scm);
				sh.Append(_T("The scheme has been added to solve two-variable unsteady PDE's\n"));
			}
			else{
				solveT3 solveptr=(solveT3)	GetProcAddress(scmdll, "solve");
				if(solveptr){
					pApp->schms[3].Add(scm);
					sh.Append(_T("The scheme has been added to solve two-variable steady PDE's\n"));
				}
				else{
					AfxMessageBox(_T("The dll does not contain a proper solve method"));
					FreeLibrary(scmdll);
					return;
				}
			}
		}
	}
	infoptr = (infoT) GetProcAddress(scmdll, "info");
	if(infoptr){
			char* ar=new char[128];
			(infoptr)(ar);
			CString s(ar);
			sh.Append(s);
	}
	FreeLibrary(scmdll);
	IDD_Info_Dialog dlg;
	int curPos=0;
	CString info= sh.Tokenize(_T("|"),curPos);
	CString link= sh.Tokenize(_T("|"),curPos);
	dlg.setInfo(info,link);
	dlg.DoModal();
}


void CwfdeqDoc::OnGraphIt()
{
	CMFCRibbonComboBox* pCombo=DYNAMIC_DOWNCAST(CMFCRibbonComboBox,pRibbon->FindByID(IDC_SOLUTION_LIST));
	int sel=pCombo->GetCurSel();
	if(sel<0){ ::AfxMessageBox(L"Please Select a Solution");	return;}

	mglGraph *gr = new mglGraph;
	mglData md;
	int x=soList[sel].uGrid.getX();
	int y=soList[sel].uGrid.getY();
	double *ar=new double[x*y];
	soList[sel].uGrid.toArray(ar);
	md.Set(ar,x,y);
	gr->Rotate(40,60);
	gr->Light(true);
	gr->Box();
	gr->Surf(md);
	gr->WriteJPEG("try.jpg");
	CImage f;
	f.Destroy();
	f.Load(_T("try.jpg"));
	IDD_GRAPH dlg;
	dlg.setPik((HBITMAP)f);
	dlg.DoModal();
}
